#include "ParticleSystem.cuh"

#include <stdio.h>

#include "..\rtCommon\cuImprovedPerlinNoise.h"
#include "..\cuCommon\cuTypes.h"

__global__
void ParticleSystem_AddPositionNoise_Kernel(float4 * pPosition, float freq, float scale, int nParticles)
{
  uint32 tid = threadIdx.x + blockIdx.x * blockDim.x;
  
  if (tid < nParticles)
  {
    float4 pos = pPosition[tid];
    float3 pn = cuImprovedPerlinNoise::cuBrownianMotionf3(xyz(pos) * freq) * scale;

    pos.x = pos.x + pn.x;
    pos.y = pos.y + pn.y;
    pos.z = pos.z + pn.z;

    pPosition[tid] = pos;
  }
}

void ParticleSystem_AddPositionNoise(float4 * pPosition, float freq, float scale, int nParticles)
{
  if (pPosition == NULL)
    return;

  dim3 block(128);
  dim3 grid ( (nParticles + block.x - 1) / block.x );

  ParticleSystem_AddPositionNoise_Kernel<<<grid, block>>>(pPosition, freq, scale, nParticles);
  cudaThreadSynchronize();

  cudaError_t error = cudaGetLastError();

  if (error != cudaSuccess)
  {
    printf("error in ParticleSystem_AddPositionNoise\n %d grid %d block", grid.x, block.x);
  }
}

__global__
void ParticleSystem_Animate_Kernel(float4 * pPosition, float4 * pVelocity, float4 forces, float damping, int nActive)
{
  uint32 tid = threadIdx.x + blockIdx.x * blockDim.x;

  if (tid < nActive)
  {
    float4 pos = pPosition[tid];
    float4 vel = pVelocity[tid];

    pos = pos + vel;
    
    pos.w = 1; // debug

    vel = vel * damping;
    vel = vel + forces;

    // TODO : set proper bnd condition 

    pPosition[tid] = pos;
    pVelocity[tid] = vel;
  }
}

void ParticleSystem_Animate(float4 * pPosition, float4 * pVelocity, float4 forces, float damping, int nActive)
{
  if (pPosition == NULL || pVelocity == NULL)
    return;

  dim3 block(128);
  dim3 grid ( (nActive + block.x - 1) / block.x );

  ParticleSystem_Animate_Kernel<<<grid, block>>>(pPosition, pVelocity, forces, damping, nActive);
  cudaThreadSynchronize();

  cudaError_t error = cudaGetLastError();

  if (error != cudaSuccess)
  {
    printf("error in ParticleSystem_Animate\n %d grid %d block", grid.x, block.x);
  }
}